home *** CD-ROM | disk | FTP | other *** search
- /*
- CalendarView.m - Copyright (c) 1992 NeXT Computer, Inc.
-
- You may freely copy, distribute and reuse the code in this example.
- NeXT Computer, Inc. disclaims any warranty of any kind, expressed or implied,
- as to its fitness for any particular use.
- */
-
- #import <ansi/ansi.h>
- #import <bsd/libc.h>
- #import <appkit/appkit.h>
- #import <dpsclient/psops.h>
- #import "CalendarView.h"
-
- #define NROWS 6
- #define NCOLS 7
- #define VIEW_BORDER 3.0
- #define CELL_SPACE 0.0 /* 2 */
- #define ITEM_SPACE 2.0
- #define TEXT_OFFSET 5.0
- #define YEAR_RANGE 10
- #define BACK_YEARS 3
-
- static char *monthStrings[] = {
- "January", "February", "March", "April", "May", "June",
- "July", "August", "September", "October", "November", "December" };
-
- static char *dayStrings[] = {
- "S", "M", "T", "W", "T", "F","S" };
-
- static char *dayNumStrings[] = {
- "1", "2", "3", "4", "5", "6","7","8","9","10",
- "11", "12", "13", "14", "15", "16","17","18","19","20",
- "21", "22", "23", "24", "25", "26","27","28","29","30",
- "31" };
-
- char myTimeZone[10];
-
- /* compare two times of hh:mm for a <= b */
- int timeLessThanOrEqual(lhour, ghour, lmin, gmin)
- int lhour;
- int ghour;
- int lmin;
- int gmin;
- {
- if (lhour > ghour)
- return FALSE;
- if ((lhour == ghour) && (lmin > gmin))
- return FALSE;
- return TRUE;
- }
-
- int todayDay()
- {
- time_t t;
- struct tm *tp;
-
- time(&t);
- tp = localtime(&t);
- return (tp->tm_mday);
- }
-
- int isToday(year, month, day)
- int year;
- int month;
- int day;
- {
- time_t t;
- struct tm *tp;
-
- year -= 1900;
- month--;
- time(&t);
- tp = localtime(&t);
- if ((year == tp->tm_year) && (month == tp->tm_mon) && (day == tp->tm_mday)) {
- return (1);
- } else {
- return (0);
- }
- return (tp->tm_mday);
-
- }
-
- int isThisMonthAndYear(year, month)
- int year;
- int month;
- {
- time_t t;
- struct tm *tp;
-
- year -= 1900;
- month--;
- time(&t);
- tp = localtime(&t);
- if ((year == tp->tm_year) && (month == tp->tm_mon)) {
- return (1);
- } else {
- return (0);
- }
- return (tp->tm_mday);
-
- }
-
- void copyTime(dest, destZone, source)
- struct tm *dest;
- char *destZone;
- struct tm *source;
- {
- dest->tm_sec = source->tm_sec;
- dest->tm_min = source->tm_min;
- dest->tm_hour = source->tm_hour;
- dest->tm_mday = source->tm_mday;
- dest->tm_mon = source->tm_mon;
- dest->tm_year = source->tm_year;
- dest->tm_wday = source->tm_wday;
- dest->tm_yday = source->tm_yday;
- dest->tm_isdst = source->tm_isdst;
- dest->tm_gmtoff = source->tm_gmtoff;
- if (source->tm_zone != NULL)
- strcpy(destZone, source->tm_zone);
- dest->tm_zone = destZone;
- }
-
- time_t myMakeTime(ntp)
- struct tm *ntp;
- {
- time_t t;
- struct tm *tp;
- int saveHour;
-
- saveHour = ntp->tm_hour;
- t = mktime(ntp);
- tp = localtime(&t);
- copyTime(ntp, myTimeZone, tp);
- ntp->tm_hour = saveHour;
- t = mktime(ntp);
- tp = localtime(&t);
- copyTime(ntp, myTimeZone, tp);
- return t;
- }
-
- void getTime(ntp)
- struct tm *ntp;
- {
- time_t t;
- struct tm *tp;
-
- time(&t);
- tp = localtime(&t);
- copyTime(ntp, myTimeZone, tp);
- }
-
- void myLocalTime(ntp, t)
- struct tm *ntp;
- time_t *t;
- {
- struct tm *tp;
-
- tp = localtime(t);
- copyTime(ntp, myTimeZone, tp);
- }
-
- int weekDayOfFirstDayOfMonth(ntp)
- struct tm *ntp;
- {
- struct tm *tp;
- time_t t;
- struct tm mt;
- char tz[10];
-
- copyTime(&mt, tz, ntp);
- mt.tm_mday = 1;
- mt.tm_hour = 8;
- t = mktime(&mt);
- tp = localtime(&t);
- return tp->tm_wday;
- }
-
- @interface LabelCell:Cell
- {
- }
- - drawSelf:(NXRect const *)r inView:controlView;
- @end
-
- @implementation LabelCell
-
- - drawInside:(NXRect const *)r inView:controlView
- {
- float w;
-
- w = [support getWidthOf:contents];
- [support set];
- PSmoveto(r->origin.x + r->size.width/2.0 - w/2.0, r->size.height - TEXT_OFFSET);
- if (cFlags1.state)
- PSsetgray(NX_DKGRAY);
- else
- PSsetgray(NX_BLACK);
- PSshow(contents);
- return self;
- }
-
- - drawSelf:(NXRect const *)r inView:controlView
- {
- [self drawInside:r inView:controlView];
- return self;
- }
-
- @end
-
- @interface DayCell:Cell
- {
- BOOL isDimmed;
- }
-
- - drawSelf:(NXRect const *)r inView:controlView;
- - setDimmed:(BOOL)theValue;
-
- @end
-
- @implementation DayCell
-
- - setDimmed:(BOOL)theValue
- {
- isDimmed = theValue;
- return self;
- }
-
- - drawInside:(NXRect const *)r inView:controlView
- {
- float w;
-
- if (cFlags1.disabled) {
- NXDrawGrayBezel(r, r);
- } else {
- NXDrawWhiteBezel(r, r);
- if (cFlags1.highlighted || cFlags1.state)
- NXHighlightRect(r);
- w = [support getWidthOf:contents];
- [support set];
- PSmoveto(/* X */ r->origin.x + r->size.width/2.0 - w/2.0,
- /* Y */ r->origin.y + r->size.height - TEXT_OFFSET);
- if (isDimmed)
- PSsetgray(NX_DKGRAY);
- else
- PSsetgray(NX_BLACK);
- PSshow(contents);
- }
- return self;
- }
-
- - drawSelf:(NXRect const *)r inView:controlView
- {
- [self drawInside:r inView:controlView];
- return self;
- }
-
- - highlight:(NXRect const *)r inView:controlView lit:(BOOL)flag
- {
- if (cFlags1.highlighted != flag) {
- cFlags1.highlighted = flag;
- if (!flag && cFlags1.state)
- return self;
- NXHighlightRect(r);
- }
- return self;
- }
-
- - read:(NXTypedStream*)s
- {
- [super read:s];
- NXReadTypes(s,"i", &isDimmed);
- return self;
- }
-
- - write:(NXTypedStream*)s
- {
- [super write:s];
- NXWriteTypes(s,"i", &isDimmed);
- return self;
- }
-
- @end
-
- @implementation CalendarView
-
- - initFrame:(NXRect const *)r
- {
- NXRect matrixRect;
- NXSize size;
- int i;
- char buf[10];
- float pos;
- id theCell;
-
- [super initFrame:r];
- matrixRect = *r;
- viewRect = *r;
- matrixRect.size.height -= VIEW_BORDER * 2;
- matrixRect.size.width -= VIEW_BORDER * 2;
- cellSize.width = floor((matrixRect.size.width - (CELL_SPACE * (NCOLS-1))) / NCOLS);
- cellSize.height = floor((matrixRect.size.height - (CELL_SPACE * (NCOLS-1))) / (NROWS+2));
- matrixRect.size.width = cellSize.width * NCOLS;
- matrixRect.size.height = NROWS * cellSize.height;
- //[self sizeTo:matrixRect.size.width + (2 * VIEW_BORDER) :r->size.height];
- bounds.size.width = matrixRect.size.width + (2 * VIEW_BORDER);
- bounds.size.height = r->size.height;
- frame.size.width = matrixRect.size.width + (2 * VIEW_BORDER);
- frame.size.height = r->size.height;
- viewRect = bounds;
-
- monthMatrix = [[Matrix alloc] initFrame:&matrixRect
- mode:NX_RADIOMODE
- cellClass:[DayCell class]
- numRows:NROWS
- numCols:NCOLS];
- size.width = CELL_SPACE;
- size.height = CELL_SPACE;
- [monthMatrix setBackgroundGray:NX_BLACK];
- [monthMatrix setIntercell:&size];
- [monthMatrix setCellSize:&cellSize];
- [monthMatrix setEmptySelectionEnabled:NO];
- [self addSubview:monthMatrix];
- [monthMatrix moveTo:VIEW_BORDER:VIEW_BORDER];
- [monthMatrix setTarget:self];
- [monthMatrix setAction:@selector(dayChanged:)];
-
-
- monthPl = [[PopUpList alloc] init];
- for (i = 0; i<12; i++) {
- [monthPl addItem:monthStrings[i]];
- }
- monthButton = NXCreatePopUpListButton(monthPl);
- [self addSubview:monthButton];
- [monthPl setTarget:self];
- [monthPl setAction:@selector(dateChanged:)];
-
- getTime(&theTime);
- yearPl = [[PopUpList alloc] init];
- yearBase = theTime.tm_year - BACK_YEARS;
- for (i = 0; i<YEAR_RANGE; i++) {
- sprintf(buf, "%d", theTime.tm_year+1900+i-BACK_YEARS);
- [yearPl addItem:buf];
- }
- yearButton = NXCreatePopUpListButton(yearPl);
- [self addSubview:yearButton];
- [yearPl setTarget:self];
- [yearPl setAction:@selector(dateChanged:)];
- [self setFonts];
- [self setupButtons];
- sprintf(buf, "%d", theTime.tm_year+1900);
- [yearButton setTitle:buf];
-
- pos = matrixRect.size.height;
- matrixRect.size.height = cellSize.height - (2 * ITEM_SPACE) - VIEW_BORDER;
- dayLabelMatrix = [[Matrix alloc] initFrame:&matrixRect
- mode:NX_TRACKMODE
- cellClass:[LabelCell class]
- numRows:1
- numCols:NCOLS];
- size.width = CELL_SPACE;
- size.height = CELL_SPACE;
- [dayLabelMatrix setBackgroundGray:NX_LTGRAY];
- [dayLabelMatrix setIntercell:&size];
- size.width = cellSize.width;
- size.height = matrixRect.size.height;
- [dayLabelMatrix setCellSize:&size];
- [self addSubview:dayLabelMatrix];
- [dayLabelMatrix moveTo:VIEW_BORDER :pos + ITEM_SPACE + VIEW_BORDER];
- for (i = 0; i<NCOLS; i++) {
- theCell = [dayLabelMatrix cellAt:0:i];
- [theCell setStringValue:dayStrings[i]];
- [theCell setFont:buttonFont];
- [theCell setState:(((i == 0) || (i == 6)) ? 1 : 0)];
- }
- [monthButton setTitle:monthStrings[theTime.tm_mon]];
- [self loadMatrix];
- useDelegate = NO;
- return self;
- }
-
- - setDelegate:anObject
- {
- delegate = anObject;
- useDelegate = YES;
- return self;
- }
-
- - setDoDelegate:anObject
- {
- delegate = anObject;
- return self;
- }
-
- -(BOOL)useDelegate
- {
- return (useDelegate);
- }
-
- /*
- ** Check for correct view type and to see of delegate outlet not yet set.
- ** If so check for object in responder chain the responds to takeStringFrom:
- ** and set that object as our delegate. However of the object has a superview
- ** that is of type CalendarView do not set delegate.
- */
- - (BOOL)acceptsFirstResponder
- {
- id temp;
-
- if ([self useDelegate] == YES) {
- return NO;
- }
-
- temp = [window firstResponder];
- while (temp) {
- if ([temp respondsTo:@selector(takeStringValueFrom:)]) {
- [self setDoDelegate:temp];
- temp = nil;
- } else {
- temp = [temp nextResponder];
- }
- }
- return YES;
- }
-
- - setFonts
- {
- int i;
-
- if (cellFont == NULL) {
- [cellFont free];
- [buttonFont free];
- }
- cellFont = [Font newFont:"Helvetica"
- size: (((MIN(cellSize.width, cellSize.height)
- - (TEXT_OFFSET * 2)) /2.0) * 2.0)
- style:0
- matrix:NX_FLIPPEDMATRIX];
- buttonFont = [Font newFont:"Helvetica-Bold"
- size: (((MIN(cellSize.width, cellSize.height)
- - (TEXT_OFFSET * 2)) /2.0) * 2.0)
- style:0
- matrix:NX_FLIPPEDMATRIX];
- for (i = 0; i < NCOLS; i++)
- [[dayLabelMatrix cellAt:0:i] setFont:buttonFont];
- return self;
- }
-
- - setupButtons
- {
- NXRect f;
- char buf[20];
-
- strcpy(buf, [monthButton title]);
- [monthButton setTitle:"0000000001"];
- [monthButton setFont:buttonFont];
- [monthPl setFont:buttonFont];
- [monthButton sizeToFit];
- [monthButton setTitle:buf];
- [monthButton getFrame:&f];
- [monthButton moveTo:VIEW_BORDER+ITEM_SPACE
- :viewRect.size.height - f.size.height - VIEW_BORDER - ITEM_SPACE];
- strcpy(buf, [yearButton title]);
- [yearButton setTitle:"00001"];
- [yearButton setFont:buttonFont];
- [yearPl setFont:buttonFont];
- [yearButton sizeToFit];
- [yearButton setTitle:buf];
- [yearButton getFrame:&f];
- [yearButton moveTo:viewRect.size.width - f.size.width - VIEW_BORDER - ITEM_SPACE
- :viewRect.size.height - f.size.height - VIEW_BORDER - ITEM_SPACE];
- return self;
- }
-
- - drawSelf:(const NXRect *)rects :(int)rectCount
- {
- PSsetgray(NX_DKGRAY);
- NXRectFill(rects);
- NXDrawGroove(rects, rects);
- return self;
- }
-
- int lastDay(month, year)
- int month;
- int year;
- {
- switch (month) {
- case 1:
- if (((year % 4) == 0) && ((year % 400) != 0))
- return 29;
- else
- return 28;
- case 3:
- case 5:
- case 8:
- case 10:
- return 30;
- default:
- return 31;
- }
- }
-
- - loadMatrix
- {
- int row;
- int col;
- int fDay;
- int lDay;
- int day = 0;
- int passedFirstDay = FALSE;
- id theCell;
-
- fDay = weekDayOfFirstDayOfMonth(&theTime);
- lDay = lastDay(theTime.tm_mon, theTime.tm_year);
- for (row = 0; row < NROWS; row++) {
- for (col = 0; col < NCOLS; col++) {
- theCell = [monthMatrix cellAt:row:col];
- if ((col == fDay) && (!passedFirstDay))
- passedFirstDay = TRUE;
- [theCell setDimmed:(((col == 0) || (col == 6)) ? YES : NO)];
- if ((passedFirstDay) && (day < lDay)) {
- [theCell setEnabled:YES];
- [theCell setStringValue:dayNumStrings[day++]];
- [theCell setFont:cellFont];
- if (day == theTime.tm_mday)
- [monthMatrix selectCellAt:row:col];
- } else {
- [theCell setEnabled:NO];
- }
- }
- }
- [monthMatrix display];
- return self;
- }
-
- - (const char *)stringValue
- {
- strftime(tbuf, 50, "%d-%B-%Y", &theTime);
- return (tbuf);
- }
-
- - dateChanged:sender
- {
- int lDay;
- int temp;
-
- temp = [monthPl indexOfItem:[monthPl selectedItem]];
- if (temp != -1)
- theTime.tm_mon = temp;
- temp = [yearPl indexOfItem:[yearPl selectedItem]];
- if (temp != -1)
- theTime.tm_year = temp + yearBase;
- lDay = lastDay(theTime.tm_mon, theTime.tm_year);
- if (theTime.tm_mday > lDay)
- theTime.tm_mday = lDay;
-
- t = myMakeTime(&theTime);
- [self loadMatrix];
- if (useDelegate == YES) {
- if ([delegate respondsTo:sel_getUid("dateDidChange:")])
- [delegate perform:sel_getUid("dateDidChange:") with:self];
- } else {
- [delegate takeStringValueFrom:self];
- }
- return self;
- }
-
- - dayChanged:sender
- {
- theTime.tm_mday = [[monthMatrix selectedCell] intValue];
- t = myMakeTime(&theTime);
- if (useDelegate == YES) {
- if ([delegate respondsTo:sel_getUid("dateDidChange:")])
- [delegate perform:sel_getUid("dateDidChange:") with:self];
- } else {
- [delegate takeStringValueFrom:self];
- }
- return self;
- }
-
- - (struct tm *)currentDate
- {
- return (&theTime);
- }
-
- - setCurrentDate:(struct tm *)theDate
- {
- char buf[20];
-
- if (![self canDraw])
- return self;
- if (theDate->tm_year >= (yearBase + YEAR_RANGE)) {
- NXRunAlertPanel("Alert", "Year is out of range in setCurrentDate", 0, 0, 0);
- return self;
- }
- copyTime(&theTime, timeZone, *theDate);
- [monthButton setTitle:monthStrings[theTime.tm_mon]];
- sprintf(buf, "%d", theTime.tm_year+1900);
- [yearButton setTitle:buf];
- [self loadMatrix];
- return self;
- }
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- NXSize matrixSize;
- NXSize size;
- float pos;
-
- matrixSize.height = height - (VIEW_BORDER * 2);
- matrixSize.width = width - (VIEW_BORDER * 2);
- cellSize.width = floor((matrixSize.width - (CELL_SPACE * (NCOLS-1))) / NCOLS);
- cellSize.height = floor((matrixSize.height - (CELL_SPACE * (NCOLS-1))) / (NROWS+2));
- matrixSize.width = cellSize.width * NCOLS;
- matrixSize.height = NROWS * cellSize.height;
- [super sizeTo:matrixSize.width + (2 * VIEW_BORDER) :height];
- viewRect = bounds;
- [monthMatrix setCellSize:&cellSize];
- [monthMatrix moveTo:VIEW_BORDER:VIEW_BORDER];
- [monthMatrix sizeTo:matrixSize.width :matrixSize.height];
-
- pos = matrixSize.height;
- matrixSize.height = cellSize.height - (2 * ITEM_SPACE) - VIEW_BORDER;
- size.width = cellSize.width;
- size.height = matrixSize.height;
- [dayLabelMatrix setCellSize:&size];
- [dayLabelMatrix moveTo:VIEW_BORDER :pos + ITEM_SPACE + VIEW_BORDER];
- [dayLabelMatrix sizeTo:matrixSize.width :matrixSize.height];
- [self setFonts];
- [self setupButtons];
- [self loadMatrix];
- return self;
- }
-
- - read:(NXTypedStream*)s
- {
- [super read:s];
- NXReadTypes(s,"@@@@@@@@@i", &delegate, &monthButton, &monthPl, &yearButton, &yearPl, &monthMatrix, &dayLabelMatrix, &cellFont, &buttonFont, &useDelegate);
- getTime(&theTime);
- yearBase = theTime.tm_year - BACK_YEARS;
- [self setCurrentDate:&theTime];
- return self;
- }
-
- - write:(NXTypedStream*)s
- {
- [super write:s];
- NXWriteTypes(s,"@@@@@@@@@i", &delegate, &monthButton, &monthPl, &yearButton, &yearPl, &monthMatrix, &dayLabelMatrix, &cellFont, &buttonFont, &useDelegate);
- return self;
- }
-
-
- @end
-